package com.gobygang.client;

/*
 * 
 */

import com.gobygang.client.Authenication.Provider;
import com.gobygang.client.Authenication.Status;
import com.gobygang.client.dialog.ProcessingDialog;
import com.gobygang.client.uibinder.Alert;
import com.gobygang.shared.ChitInfo;
import com.gobygang.shared.ContactInfo;
import com.gobygang.shared.LoginInfo;
import com.gobygang.shared.RouteInfo;
import com.gobygang.shared.TaxiGangInfo;
import com.gobygang.shared.TaxiGangInfo.LeaveResult;
import com.gobygang.shared.TaxiGanguserInfo;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * Provides responses for queries made to the SuggestBox
 */

public class GobygangHandler {
	public enum Success {
		NONE, UPDATE, JOIN, CREATE
	};

	public enum Crud {
		CREATE, REPLACE, UPDATE, DELETE
	};

	private final GobygangServiceAsync gobygangService = GWT
			.create(GobygangService.class);
	private final LoginServiceAsync loginService = GWT
			.create(LoginService.class);

	// private boolean online=true;
	public static DateTimeFormat formatter = DateTimeFormat
			.getFormat("EEE, MMM d, hh:mm a");

	private static GobygangHandler instance = new GobygangHandler();

	public static GobygangHandler getInstance() {
		return instance;
	}

	public void addMessage(final TaxiGangInfo taxiganginfo, String message) {
		final Session session = Session.getInstance();
		gobygangService.addMessage(taxiganginfo, session.getLoginInfo(),
				message, new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
						showSorry("add message");
					}

					public void onSuccess(Void v) {
						gobygangService.getMyTaxiGangs(session.getLoginInfo(),
								new AsyncCallback<TaxiGangInfo[]>() {
									public void onFailure(Throwable error) {
										showSorry("get my taxigangs during add message");
									}

									public void onSuccess(
											TaxiGangInfo[] taxigangInfoList) {
										session.setMyTaxiGangInfoList(taxigangInfoList);
										session.setCurrentMyTaxiGang(taxiganginfo);
										GobygangPresenter.getInstance()
												.displayMessages();
									}
								});

					}
				});
	}

	public void clickedToDeleteClosedTaxiGang(TaxiGangInfo taxiganginfo) {
		gobygangService.deleteTaxiGang(taxiganginfo, new AsyncCallback<Void>() {
			public void onFailure(Throwable error) {
				showSorry("clickedToDeleteClosedTaxiGang");
			}

			public void onSuccess(Void v) {
				// displayMyTaxiGangsList();
				// tabPanel.selectTab(1);

			}
		});
	}

	public String invitationMessage() {
		String msgBody = Text.t.invitationGreeting()
				+ "\n";
		;
		msgBody += Text.t.from() + ":"
				+ "***START***" + "\n";
		msgBody += Text.t.to() + ":"
				+ "***DESTINATION***" + "\n";
		msgBody += Text.t.time() + ":"
				+ "***TIME***" + "\n";
		msgBody += Text.t.invitationLink() + "\n\n";
		return msgBody;
	}

	public void createTaxiGang(ChitInfo info) {
		//Log.info("GobygangPresenter:createTaxiGang:" + info.getChitText());

		final Session session = Session.getInstance();
		TaxiGangInfo taxiGangInfo = session.getSearchTaxiGangInfo();
		String invitationMessage = invitationMessage();

		taxiGangInfo.setInvitationMessage(invitationMessage);
//		Log.info("GobygangPresenter:createTaxiGang:"
//				+ taxiGangInfo.getDepartureHour() + ":"
//				+ taxiGangInfo.getDepartureMinute());
		LoginInfo loginInfo = session.getLoginInfo();
		gobygangService.createTaxiGang(taxiGangInfo, loginInfo, info,
				new AsyncCallback<TaxiGangInfo>() {
					public void onFailure(Throwable error) {
						showSorry("createTaxiGang");
					}

					public void onSuccess(TaxiGangInfo taxiGangInfo) {
						searchForMyTaxiGangs(Success.CREATE, taxiGangInfo);
					}
				});
	}

	public void joinTaxiGang(ChitInfo chitInfo) {
		final Session session = Session.getInstance();
		final TaxiGangInfo taxiGangInfo = session.getJoinTaxiGangInfo();
		gobygangService.joinTaxiGang(taxiGangInfo, session.getLoginInfo(),
				chitInfo, new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
						showSorry("joinTaxiGang");
					}

					public void onSuccess(Void v) {
						searchForMyTaxiGangs(Success.JOIN, taxiGangInfo);
						// tabPanel.selectTab(1);
					}
				});
	}


	public void searchForTaxiGangs() {
		final Session session = Session.getInstance();

		TaxiGangInfo taxiganginfo = session.getSearchTaxiGangInfo();

		gobygangService.getTaxiGangs(taxiganginfo,
				new AsyncCallback<TaxiGangInfo[]>() {
					public void onFailure(Throwable error) {
						showSorry("searchForTaxiGangs");
					}

					public void onSuccess(TaxiGangInfo[] taxigangInfoList) {
						session.setTaxiGangSearchResultList(taxigangInfoList);
						GobygangPresenter.getInstance().displayTaxiGangsList();

					}
				});

	}

	public void leaveTaxiGang(boolean confirm) {
		if (!confirm) {
			Command cmd = new Command() {
				public void execute() {
					GobygangHandler.getInstance().leaveTaxiGang(true);
				}
			};
			Alert.alert(cmd, Text.t.leave()
					+ "Taxigang",
					Text.t.reallyWantToLeave(),
					true, "422px");

			return;
		}
		final Session session = Session.getInstance();
		gobygangService.leaveTaxiGang(session.getCurrentMyTaxiGang(),
				session.getLoginInfo(), new AsyncCallback<LeaveResult>() {
					public void onFailure(Throwable error) {
						showSorry("leaveTaxiGang");
					}

					public void onSuccess(LeaveResult leaveResult) {
						switch (leaveResult) {
						case OK:
							searchForMyTaxiGangs(Success.NONE, null);
							break;
						case CANT_LEAVE:
							GobygangPresenter.getInstance().showCantLeave();
							break;
						}
					}
				});

	}

	public void award() {
		final Session session = Session.getInstance();
		gobygangService.award(session.getCurrentMyTaxiGang(),
				session.getLoginInfo(), new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
						showSorry("leaveTaxiGang");
					}

					public void onSuccess(Void leaveResult) {
						searchForMyTaxiGangs(Success.NONE, null);
					}
				});

	}

	public void deleteTaxiGang(boolean confirm) {
		if (!confirm) {
			Command cmd = new Command() {
				public void execute() {
					GobygangHandler.getInstance().deleteTaxiGang(true);
				}
			};
			Alert.alert(cmd, Text.t.delete()
					+ "Taxigang",
					Text.t.reallyWantToDelete(),
					true, "422px");

			return;
		}
		final Session session = Session.getInstance();
		gobygangService.deleteTaxiGang(session.getCurrentMyTaxiGang(),
				new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
						showSorry("deleteTaxiGang");
					}

					public void onSuccess(Void v) {
						searchForMyTaxiGangs(Success.NONE, null);
					}
				});

	}

	public void searchForMyTaxiGangs(final Success success,
			final TaxiGangInfo myCurrentTaxiGang) {
		ProcessingDialog.show(Text.t.processing());
		//Log.info("GobygangHandler:searchForMyTaxiGangs");
		final Session session = Session.getInstance();
		TaxiGanguserInfo taxiGanguserInfo = session.getTaxiGangUserInfo();
		if (taxiGanguserInfo != null) {
			session.getLoginInfo().setId(taxiGanguserInfo.getId());
			//Log.info("searchForMyTaxiGangs uid="
//					+ session.getLoginInfo().getId() + " "
//					+ taxiGanguserInfo.getDisplayName());
			gobygangService.getMyTaxiGangs(session.getLoginInfo(),
					new AsyncCallback<TaxiGangInfo[]>() {
						public void onFailure(Throwable error) {
							ProcessingDialog.hide();
							showSorry("searchForMyTaxiGangs:" + success);
						}

						public void onSuccess(TaxiGangInfo[] taxigangInfoList) {
							ProcessingDialog.hide();
							//Log.info("searchForMyTaxiGangs no. of my taxigangs ="
							//		+ taxigangInfoList.length);
							if (taxigangInfoList.length > 0) {
								//Log.info("searchForMyTaxiGangs id of first ="
							//			+ taxigangInfoList[0].getId());
							}
							session.setMyTaxiGangInfoList(taxigangInfoList);
							if (myCurrentTaxiGang != null) {
								session.setCurrentMyTaxiGang(myCurrentTaxiGang);
							}
							GobygangPresenter.getInstance()
									.displayMyTaxiGangsList();
							GobygangPresenter.getInstance()
									.showSuccess(success);
						}
					});
		} else {
			//Log.error("searchForMyTaxiGangs but taxiGanguserInfo is null!");
		}

	}

	public void deleteAllTaxiGangs() {
		gobygangService.deleteAllTaxiGangs(new AsyncCallback<Void>() {
			public void onFailure(Throwable error) {
				showSorry("deleteAllTaxiGangs");
			}

			public void onSuccess(Void v) {
				Window.alert("deleted all tagigangs");
			}
		});
	}


	public void loginToGoogle(String uri) {
		//Log.info("loginToGoogle with url: " + uri);
		loginService.login(uri, new AsyncCallback<LoginInfo>() {
			public void onFailure(Throwable error) {
				Window.alert("login problem:" + error.getMessage());
			}

			public void onSuccess(LoginInfo loginInfo) {
				//Log.info("loginToGoogle: onSuccess: " + loginInfo.isLoggedIn());
				Authenication authentication = Authenication.getInstance();
				Status status = Status.LoggedOut;
				if (loginInfo.isLoggedIn()) {
					if (authentication.getLoggedoutResolved(Provider.Google,
							Status.LoggedIn)) {
						//Log.info("loginToGoogle:loggedinresolved:google");
						Session.getInstance().setLoginInfo(loginInfo);
						GobygangPresenter.getInstance().authenticationComplete(
								true);

						//Log.info("loginToGoogle:loggedoutresolved:google complete");
					}

				} else {
					if (authentication.getLoggedoutResolved(Provider.Google,
							Status.LoggedOut)) {
						//Log.info("loginToGoogle:loggedoutresolved:google");
						// Window.alert ("fb resolved: "+result);
						// Window.alert ( "not logged in - show login" );
						Session.getInstance().setLoginInfo(loginInfo);
						GobygangPresenter.getInstance().authenticationComplete(
								true);

						//Log.info("loginToGoogle:loggedoutresolved:google complete");
					} else {
						//Log.info("loginToGoogle:onSuccess: !loggedoutresolved:google");
					}

				}
				authentication.setAuthStatus(Provider.Google, status);
				// //Log.info("getTaxiGangUser:"+loginInfo.isLoggedIn());
				// if (welcomePresenter==null){
				// //Log.error("welcomePresenter is null");
				// }else{
				// Session session = Session.getInstance();
				// session.setLoginInfo(loginInfo);
				// welcomePresenter.handleGoogleResponse(loginInfo);
				// }
			}
		});

	}

	//@Override
	public void getTaxiGangUser() {
		final Session session = Session.getInstance();
		//Log.info("getTaxiGangUser:" + session.getLoginInfo().getId());
		gobygangService.getTaxiGangUser(session.getLoginInfo(),
				new AsyncCallback<TaxiGanguserInfo>() {
					public void onFailure(Throwable error) {
						showSorry("getTaxiGangUser problem: "
								+ session.getLoginInfo().getId());
					}

					public void onSuccess(TaxiGanguserInfo taxigangUserInfo) {
						//Log.info("getTaxiGangUser:" + taxigangUserInfo);
						logInfo("LOGIN:" + taxigangUserInfo.getDisplayName());
						session.setTaxiGangUserInfo(taxigangUserInfo);
						// GobygangPresenter.getInstance().initOracle();
						// welcomePresenter.handleGotUser(taxigangUserInfo);
						// searchForMyTaxiGangs(Success.NONE);

					}
				});

	}

	public void showInvitation() {
		final Session session = Session.getInstance();
		//Log.info("showInvitation:" + session.getRef());
		gobygangService.getInvitation(session.getRef(),
				new AsyncCallback<TaxiGangInfo>() {
					public void onFailure(Throwable error) {
						showSorry("getTaxiGangUser problem: "
								+ session.getLoginInfo().getId());
					}

					public void onSuccess(TaxiGangInfo taxigangInfo) {
						if (taxigangInfo != null) {
							TaxiGangInfo[] resultSearchList = { taxigangInfo };
							session.setTaxiGangSearchResultList(resultSearchList);
						} else {
							TaxiGangInfo[] resultSearchList = {};
							session.setTaxiGangSearchResultList(resultSearchList);
						}
						GobygangPresenter.getInstance().displayTaxiGangsList();
					}
				});

	}

	public void getPartner(final String partnerRef, final Command cmd) {
		//Log.info("showPartner:" + partnerRef);
		gobygangService.getPartner(partnerRef, new AsyncCallback<RouteInfo>() {
			public void onFailure(Throwable error) {
				showSorry("getPartner problem: " + partnerRef);
			}

			public void onSuccess(RouteInfo partnerInfo) {
				// partnerInfo = new PartnerInfo();
				// partnerInfo.setLat(48);
				// partnerInfo.setLng(11);
				Session.getInstance().setRoute(partnerInfo);
				cmd.execute();
			}
		});

	}

	public void getRoute(final String ref, final Command cmd) {
		//Log.info("getRoute:" + ref);
		gobygangService.getRoute(ref, new AsyncCallback<RouteInfo>() {
			public void onFailure(Throwable error) {
				showSorry("getPartner problem: " + ref);
			}

			public void onSuccess(RouteInfo routeInfo) {
				// partnerInfo = new PartnerInfo();
				// partnerInfo.setLat(48);
				// partnerInfo.setLng(11);
				Session.getInstance().setRoute(routeInfo);
				cmd.execute();
			}
		});

	}

	public void showWishRouteCancel() {
		final Session session = Session.getInstance();
		//Log.info("showWishRouteCancel:" + session.getWishRouteCancel());
		gobygangService.cancelWishRoute(session.getWishRouteCancel(),
				new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
						showSorry("getTaxiGangUser problem: "
								+ session.getLoginInfo().getId());
					}

					public void onSuccess(Void v) {

						Window.alert("Wish route cancelled");
						ProcessingDialog.hide();

					}
				});

	}

	public void logInfo(String infoMessage) {
		gobygangService.logInfo(infoMessage, new AsyncCallback<Void>() {
			public void onFailure(Throwable error) {
				showSorry("getTaxiGangUser problem: ");
			}

			public void onSuccess(Void v) {
				// searchForMyTaxiGangs();
				// tabPanel.selectTab(1);
			}
		});
	}


	private void showSorry(String operation) {
		//Log.error("Error in GobygangHandler:" + operation);
		Alert.alert(null, "Problem",
				Text.t.sorryProblem(), false,
				"422px");
	}

	public void createWishRoute() {
		TaxiGangInfo taxiGangInfo = Session.getInstance()
				.getSearchTaxiGangInfo();
		LoginInfo loginInfo = Session.getInstance().getLoginInfo();
		gobygangService.createWishRoute(taxiGangInfo, loginInfo,
				new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
						showSorry("getTaxiGangUser problem: ");
					}

					public void onSuccess(Void v) {
						// searchForMyTaxiGangs();
						// tabPanel.selectTab(1);
					}
				});

	}


	public void sendContactInfo(ContactInfo info) {
		gobygangService.sendContactInfo(info, new AsyncCallback<Void>() {
			public void onFailure(Throwable error) {
				showSorry("getTaxiGangUser problem: ");
			}

			public void onSuccess(Void v) {
				// searchForMyTaxiGangs();
				// tabPanel.selectTab(1);
			}
		});

	}

	public void runCron() {
		String cron = Session.getInstance().getCron();
		gobygangService.runCron(cron, new AsyncCallback<Void>() {
			public void onFailure(Throwable error) {
				showSorry("getTaxiGangUser problem: ");
			}

			public void onSuccess(Void v) {
				// searchForMyTaxiGangs();
				// tabPanel.selectTab(1);
			}
		});

	}

}